package com.shenmazong.serverapisafe.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * @program: server-java-demo
 * @description: ApiInterceptor
 * @author: 亮子说编程
 * @create: 2020-12-01 08:52
 **/
public class ApiInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("==== finish ====");
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();

            // 获取注解信息
            ApiLimit apiLimit = method.getAnnotation(ApiLimit.class);

            // 如果有注解
            if(!ObjectUtils.isEmpty(apiLimit)) {
                // 获取注解参数
                int count = apiLimit.count();
                int time = apiLimit.time();

                // 获取请求者的IP
                String ip = request.getRemoteAddr();
                String requestURI = request.getRequestURI();

                // 使用apiKey+ip+url作为key
                String redisKey = "apiKey_" + ip + "_" + requestURI;
                System.out.println("redisKey======>" + redisKey);

                String obj = stringRedisTemplate.opsForValue().get(redisKey);
                if (ObjectUtils.isEmpty(obj)) {

                    Long times = stringRedisTemplate.opsForValue().increment(redisKey, 1L);
                    stringRedisTemplate.expire(redisKey, time ,TimeUnit.SECONDS);

                    System.out.println("当前访问次数：" + times);
                } else {
                    Long times = Long.parseLong(obj);
                    if(times >= count) {
                        //throw new RuntimeException("访问太频繁了，请休息一会");
                        throw  new ApiLimitException(405, "访问太频繁了，请休息一会");
                        //System.out.println("访问太频繁了，请休息一会");
                        //return false;
                    }

                    // 计算剩余的过期时间
                    stringRedisTemplate.opsForValue().increment(redisKey, 1L);
                    Long expire = stringRedisTemplate.getExpire(redisKey, TimeUnit.SECONDS);
                    stringRedisTemplate.expire(redisKey, expire ,TimeUnit.SECONDS);

                    System.out.println("当前访问次数：" + stringRedisTemplate.opsForValue().get(redisKey));
                }
            } else {
                return true;
            }
        }
        return true;
    }


}
